package android.Spider;

import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;

public final class Questions
{
	class Question
	{
		class Answer
		{
			String 	m_strFrom;
			int 	m_nOption;
		};
		
		long 				m_idQuestion = -1;							// Question ID unique for question sender
		String 				m_strOwner;									// Owner of this question
		String 				m_strMsg;									// Question body
		List<String> 		m_lstOptions = new ArrayList<String>();		// Which options we have in this question
		List<String>		m_lstFrom = new ArrayList<String>();		// Path representing the "road" of the question
		List<String>		m_lstTo = new ArrayList<String>();			// To whom question was sent/forwarded
		boolean 			m_bAllowForward;							// Is it allowed to forward this message
		
		boolean 			m_bReceived;								// Did we receive this question or we initiated a question.
		boolean 			m_bAnswered;								// If question is received, it is automatically unanswered. Later it can be answered.

		ArrayList<Answer> 	m_arrAnswers = new ArrayList<Answer>();		// Answers to this question

		void AddAnswer(String strFrom, int nOption)
		{
			synchronized(this)
			{
				// Check if this question already has answer from this person.
				Answer answer = null;
				for (int i = 0; i < m_arrAnswers.size(); ++i)
				{
					if (m_arrAnswers.get(i).m_strFrom.equals(strFrom))
					{
						answer = m_arrAnswers.get(i);
						break;
					}
				}
				
				if (answer == null)
				{
					answer = new Answer();
					answer.m_strFrom = strFrom;
					answer.m_nOption = nOption;
					m_arrAnswers.add(answer);
				}
				else
				{
					answer.m_nOption = nOption;
				}

				m_bAnswered = true;
			}
		}
		
		int GetAnswerCount(int nOption)
		{
			int nResult = 0;
			
			for (int i = 0; i < m_arrAnswers.size(); ++i)
			{
				if (m_arrAnswers.get(i).m_nOption == nOption)
					++nResult;
			}
			
			return nResult;
		}
		
		int GetTotalAnswerCount()
		{
			return m_arrAnswers.size();
		}

		void read(ObjectInputStream in) throws IOException
		{
			try {
				m_idQuestion = in.readLong();
				m_strOwner = (String)in.readObject();
				m_strMsg = (String)in.readObject();
				
				m_lstOptions = Serializer.LoadStrings(in);
				m_lstFrom = Serializer.LoadStrings(in);
				m_lstTo = Serializer.LoadStrings(in);

				m_bAllowForward = in.readBoolean();
				m_bReceived = in.readBoolean();
				m_bAnswered = in.readBoolean();
				
				int nCount = in.readInt();
				m_arrAnswers = new ArrayList<Answer>(nCount);
				for (int i = 0; i < nCount; ++i)
				{
					String str = (String)in.readObject();
					int nOption = in.readInt();
					AddAnswer(str, nOption);
				}
			}
			catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		
		void write(ObjectOutputStream out) throws IOException
		{
			out.writeLong(m_idQuestion);
			out.writeObject(m_strOwner);
			out.writeObject(m_strMsg);
			
			Serializer.Store(out, m_lstOptions);
			Serializer.Store(out, m_lstFrom);
			Serializer.Store(out, m_lstTo);

			out.writeBoolean(m_bAllowForward);
			out.writeBoolean(m_bReceived);
			out.writeBoolean(m_bAnswered);
			
			int nCount = m_arrAnswers.size();
			out.writeInt(nCount);
			for (int i = 0; i < nCount; ++i)
			{
				Answer answer = m_arrAnswers.get(i);
				out.writeObject(answer.m_strFrom);
				out.writeInt(answer.m_nOption);
			}
		}

	};

	private Questions(Context ctx)
	{
		m_questions = new ArrayList<Question>();
		
		// Read from the file.
		m_ctx = ctx;

		try
		{
			FileInputStream stream = ctx.openFileInput(s_strFileName);
			ObjectInputStream istream = new ObjectInputStream(stream);
			
			int nSize = istream.readInt();
			m_questions = new ArrayList<Question>(nSize);
			for (int i = 0; i < nSize; ++i)
			{
				Question q = new Question();
				q.read(istream);
				if (q.m_strOwner.length() > 0)
					m_questions.add(q);
			}
		}
		catch (FileNotFoundException e) {
			System.out.println(e.toString());
		}
		catch (EOFException e) {
			System.out.println(e.toString());
		}
		catch (IOException e) {
			System.out.println(e.toString());
		}
	}
	
	public static Questions Instance(Context ctx)
	{
		if (m_this == null)
			m_this = new Questions(ctx);

		return m_this;
	}

	public Question CreateQuestion() { return new Question(); }
	
	public Question GetQuestion(long idQuestion)
	{
		Question result = null;
		
		for (int i = 0; i < m_questions.size(); ++i)
		{
			Question q = m_questions.get(i);
			if (q.m_idQuestion == idQuestion)
			{
				result = m_questions.get(i);
				break;
			}			
		}				
		
		return result;
	}
	
	public void AddQuestion(
			String strOwner,
			long idQuestion,
			String strMsg, 
			List<String> lstOptions, 
			List<String> lstFrom,
			List<String> lstTo,
			boolean bAllowForward,
			boolean bReceived)
	{
		if (strOwner.length() > 0)
		{
			// First we need to check if we already have this question.
			Question q = new Question();
			q.m_idQuestion = idQuestion;
			q.m_strOwner = strOwner;
			q.m_strMsg = strMsg;
			q.m_lstOptions = lstOptions;
			q.m_lstFrom = lstFrom;
			q.m_lstTo = lstTo;
			q.m_bAllowForward = bAllowForward;
			q.m_bReceived = bReceived;
			q.m_bAnswered = !bReceived;
			AddQuestion(q);
		}
	}
	
	public void AddQuestion(Question q)
	{
		synchronized (this)
		{
			Question question = GetQuestion(q.m_idQuestion);
			if (question == null)
			{
				m_questions.add(q);
			}
			else
			{
				// We already have this question. We will just replace old information with new.
				question.m_strMsg = q.m_strMsg;
				question.m_lstOptions = q.m_lstOptions;
				question.m_lstFrom = q.m_lstFrom;
				question.m_lstTo = q.m_lstTo;
				question.m_bAllowForward = q.m_bAllowForward;
				question.m_bReceived = q.m_bReceived;
				question.m_bAnswered = q.m_bAnswered;
			}
		}
	}

	public void AddAnswer(long idQuestion, String strFrom, int nOption)
	{
		Question q = GetQuestion(idQuestion);
		if (q != null)
			q.AddAnswer(strFrom, nOption);
	}

	public void Store()
	{
		synchronized (this)
		{
			try {
				m_ctx.deleteFile(s_strFileName);
				FileOutputStream stream = m_ctx.openFileOutput(s_strFileName, Context.MODE_APPEND);
				ObjectOutputStream ostream = new ObjectOutputStream(stream);
				
				int nSize = m_questions.size();
				ostream.writeInt(nSize);
				for (int i = 0; i < nSize; ++i)
					m_questions.get(i).write(ostream);
				
				ostream.close();
				stream.close();
			}
			catch (FileNotFoundException e) {
				e.printStackTrace();
			}
			catch (NotSerializableException e) {
				e.printStackTrace();
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	// Later those two Unanswered methods should be optimized so that
	// access would be faster. We should have separated container
	// which will contain indexes of unanswered questions.
	int GetUnansweredCount()
	{
		int nCount = 0;
		
		int nSize = m_questions.size();
		for (int i = 0; i < nSize; ++i)
		{
			if (!m_questions.get(i).m_bAnswered)
				++nCount;
		}

		return nCount;		
	}
	
	Question GetUnanswered()
	{
		Question q = null;
		
		int nSize = m_questions.size();
		for (int i = 0; i < nSize && q == null; ++i)
		{
			if (!m_questions.get(i).m_bAnswered)
				q = m_questions.get(i);
		}
		
		return q;
	}
	
	List<Questions.Question> GetQuestions(String strOwner)
	{
		ArrayList<Question> lstQuestions = new ArrayList<Question>();
		
		for (int i = 0; i < m_questions.size(); ++i)
			if (m_questions.get(i).m_strOwner.equals(strOwner))
				lstQuestions.add(m_questions.get(i));
		
		return lstQuestions;
	}
	
	void Delete(long idQuestion)
	{
		for (int id = 0; id < m_questions.size(); ++id)
		{
			if (m_questions.get(id).m_idQuestion == idQuestion)
			{
				m_questions.remove(id);
				Store();
				return;
			}
		}
	}

	private static final String s_strFileName = "Questions.dat";
	private static Questions 	m_this = null;
	private ArrayList<Question>	m_questions;
	private Context 			m_ctx;
}
